
/**
 * @author   Ivan Andonov
 * @email:   ivan.andonov[at]gmail[dot]com
 *
 * @require  sjs, sjs.ShortcutCall
 * @use      sjs.Style, sjs.Arrays, sjs.Objects
 * @optional 
 **/

(function() {
sjs.create('sjs.Utils', {
			
		// PUBLIC STATIC METHODS
		callJS : function() {
			var arr = sjs.Arrays.copyArray(arguments);
			return eval(arr[0]).apply(null, arr.slice(1));
		},
		
		// BROWSER SPECIFIC
		// browser check
		isOpera : function() {
			return navigator.userAgent.indexOf('Opera') != -1;
		},
		
		isIE : function() {
			return navigator.userAgent.indexOf('MSIE') != -1;
		},
		
		isIE6 : function() {
			return !!navigator.appVersion.match(/MSIE 6/i);
		},
		isIE7 : function() {
			return !!navigator.userAgent.match(/MSIE 7/i);
		},
		
		isMoz : function() {
			return !!navigator.userAgent.match(/gecko/i);
		},
		
		// find elements
		element : function(layer) {
			if (!layer || typeof(layer) != 'string' || !layer.length) {
				return layer;
			}
			return document.getElementById(layer);
		},
		
		getElementsByClassName : function(layer, classes, strTagName, match, conversely) {
			layer = $element(layer) || $body();
			var result = [];
			if (layer) {
				if (strTagName == null) {
					strTagName = '*';
				}
				var arrElements = [];
				if (strTagName == '*' && layer.all != null) {
					arrElements = layer.all;
				} else if (layer.getElementsByTagName != null) {
					arrElements = layer.getElementsByTagName(strTagName);
				} else if (layer.all != null) {
					arrElements = layer.all;
				}
				var elmnt;
				for (var i = 0; i < arrElements.length; i++) {
					elmnt = arrElements[i];
					if (classes == null) {
						if (!elmnt.className.length) {
							if (!conversely) {
								result.push(elmnt);
							}
						} else if (conversely) {
							result.push(elmnt);
						}
					} else if ((elmnt.className && elmnt.className.length) || conversely) {
						var elmntClasses = elmnt.className.split(' ');
						if (typeof(classes) == 'string') {
							if (classes == '*') {
								if (elmnt.className.length) {
									if (!conversely) {
										result.push(elmnt);
									}
								} else if (conversely) {
									result.push(elmnt);
								}
							} else {
								if (match) {
									var matched = 0;
									var tmpClasses = classes.split(' ');
									sjs.Objects.each(
										elmntClasses,
										function(props, value, obj) {
											if (sjs.Arrays.inArray(tmpClasses, value)) {
												matched++;
											}
										}
									);
									/*for (var cls in elmntClasses) {
										if (sjs.Arrays.inArray(tmpClasses, elmntClasses[cls])) {
											matched++;
										}
									}*/
									if (matched == tmpClasses.length) {
										if (!conversely) {
											result.push(elmnt);
										}
									} else if (conversely) {
										result.push(elmnt);
									}
								} else if (elmnt.className == classes) {
									if (!conversely) {
										result.push(elmnt);
									}
								} else if (conversely) {
									result.push(elmnt);
								}
							}
						} else if (typeof(classes) == 'object' && classes.length) {
							var doAdd = false;
							for (var j = 0; j < classes.length; j++) {
								if (!sjs.Arrays.inArray(result, elmnt)) {
									if (match) {	
										var matched = 0;
										var tmpClasses = classes[j].split(' ');
										sjs.Objects.each(
											elmntClasses,
											function(prop, value, obj) {
												if (sjs.Arrays.inArray(tmpClasses, value)) {
													matched++;
												}
											}
										);
										/*for (var cls in elmntClasses) {
											if (sjs.Arrays.inArray(tmpClasses, elmntClasses[cls])) {
												matched++;
											}
										}*/
										if (matched == tmpClasses.length) {
											if (!conversely) {
												doAdd = true;
											} else {
												doAdd = false;
												break;
											}
										} else if (conversely) {
											doAdd = true;
										}
									} else if (classes[j] == elmnt.className) {
										if (!conversely) {
											doAdd = true;
										} else {
											doAdd = false;
											break;
										}
									} else if (conversely) {
										doAdd = true;
									}
								}
							}
							if (doAdd) result.push(elmnt);
						}
					}
				}
			}
			return result;
		},
		
		getBody : function() {
			return document.body || document.getElementsByTagName('body')[0];
		},
		
		getHead : function() {
			return document.getElementsByTagName('head')[0];
		},
		
		getFlashMovie : function(id) {
			if (window.document[id]) {
				return window.document[id];
			}
			if (!isIE()) {
				if (document.embeds && document.embeds[id]) {
					return document.embeds[id];
				}
			}
			return document.getElementById(id);
		},
		
		// element position
		getElementX : function(el) {
			el = $element(el);
			var x = 0;
			if (el) {
				if (el.offsetParent) {
					x = el.offsetLeft;
					el = el.offsetParent;
					while (el) {
						x += el.offsetLeft;
						el = el.offsetParent;
					}
				} else if (el.x) {
					x = el.x;
				}
			}
			return x;
		},
		
		getElementY : function(el) {
			el = $element(el);
			var y = 0;
			if (el) {
				if(el.offsetParent) {
					y = el.offsetTop;
					el = el.offsetParent;
					while(el) {
						y += el.offsetTop;
						el = el.offsetParent;
					}
				} else if (el.y) {
					y = el.y;
				}
			}
			return y;
		},
		
		getElementWidth : function(obj) {
			obj = $element(obj);
			return obj ? obj.offsetWidth : 0;
		},
		
		getElementHeight : function(obj) {
			obj = $element(obj);
			return obj ? obj.offsetHeight : 0;
		},
		
		// page offset
		getPageXScroll : function() {
			//return (window.pageXOffset ? window.pageXOffset : (document.documentElement && document.documentElement.scrollLeft != null) ? document.documentElement.scrollLeft : document.body.scrollLeft)||0;
			return Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
		},
		
		getPageYScroll : function() {
			//return (window.pageYOffset ? window.pageYOffset : (document.documentElement && document.documentElement.scrollTop != null) ? document.documentElement.scrollTop : document.body.scrollTop)||0;
			return Math.max(document.documentElement.scrollTop, document.body.scrollTop);
		},
		
		// document and screen dimentions
		getDocumentHeight : function() {
			var scrollHeight = (document.compatMode != 'CSS1Compat') ? document.body.scrollHeight : document.documentElement.scrollHeight;
			return Math.max(scrollHeight, this.getViewportHeight());
		},
		
		getDocumentWidth : function() {
			var scrollWidth = (document.compatMode != 'CSS1Compat') ? document.body.scrollWidth : document.documentElement.scrollWidth;
			return Math.max(scrollWidth, this.getViewportWidth());
		},
		
		getViewportHeight : function() {
			var mode = document.compatMode;
			if ((mode || this.isIE()) && !this.isOpera()) { // IE, Gecko
				return (mode == 'CSS1Compat') ? document.documentElement.clientHeight : document.body.clientHeight; // ? Standards : Quirks
			}
			return self.innerHeight; // Safari, Opera
		},
		
		getViewportWidth : function() {
			var mode = document.compatMode;
			if (mode || this.isIE()) { // IE, Gecko, Opera
				return (mode == 'CSS1Compat') ? document.documentElement.clientWidth : document.body.clientWidth; // ? Standards : Quirks
			}
			return self.innerWidth; // Safari
		},
		
		// Focus
		
		focus : function(el) {
			try {
				$element(el).focus();
			} catch(e){};
		},
		
		blur : function(el) {
			try {
				$element(el).blur();
			} catch(e){};
		},
		
		onFocus : function(el, def, select, toPass) {
			el = $element(el);
			if (el && el.value == def) {
				el.value = '';
				if (toPass) {
					el.type = 'password';
				}
				if (select) {
					el.select();
				}
			}
		},
		
		onBlur : function(el, def, toText) {
			el = $element(el);
			if (el && !el.value.split(' ').join('').length) {
				el.value = def;
				if (toText) {
					el.type = 'text';
				}
			}
		},
		
		// class manipulation
		addClass : function(el, cls) {
			el = $element(el);
			if (el) {
				if (this.hasClass(el)) {
					el.className = (el.className.length ? el.className+' ' : '')+cls;
				}
			}
		},
		
		removeClass : function(el, cls) {
			el = $element(el);
			if (el) {
				// remove class
				el.className = el.className.replace(new RegExp('(.*)\\b'+cls+'\\b(.*)'), '$1$2');
				// remove extra spaces
				el.className = el.className.replace(new RegExp('^\\s+|\\s+$/g'), ''); // trim
				el.className = el.className.replace('  ', ' '); // double space
			}
		},
		
		hasClass : function(el, cls) {
			el = $element(el);
			if (el) {
				if (typeof(el.className) == 'string') {
					return (new RegExp('\\b'+cls+'\\b')).test(el.className)
				}
			}
		},
		
		// visibility of the elements
		showElements : function() {
			for (var i = 0; i < arguments.length; i++) {
				$style(arguments[i], 'display', 'block');
			}
		},
		
		hideElements : function() {
			for (var i = 0; i < arguments.length; i++) {
				$style(arguments[i], 'display', 'none');
			}
		},
		
		switchElements : function() {
			for (var i = 0; i < arguments.length; i++) {
				$style(arguments[i], 'display', this.isVisible(arguments[i]) ? 'none' : 'block');
			}
		},
		
		isVisible : function(id) {
			return $style(id, 'display') != 'none';
		},
		
		// Content
		
		setHtml : function(id, str) {
			$element(id).innerHTML = str;
		},
		
		getHtml : function(id) {
			return $element(id).innerHTML;
		},
		
		// HTML ELEMENTS
		
		selects : null,
		
		isSelectsVisible : true,
		
		// show hide all select elements
		showSelects : function() {
			//Debug.log('showSelects');
			if (!this.isSelectsVisible) {
				sjs.Objects.each(this.selects, function(prop, value, obj) {
					$style(value, 'visibility', 'visible');
				});
				/*for (var i in this.selects) {
					$style(this.selects[i], );
				}*/
				this.isSelectsVisible = true;
			}
		},
		
		hideSelects : function() {
			//Debug.log('hideSelects');
			if (this.isSelectsVisible) {
				if (this.selects == null) {
					this.selects = document.getElementsByTagName('select');
				}
				sjs.Objects.each(this.selects, function(prop, value, obj) {
					$style(value, 'visibility', 'hidden');
				});
				/*for (var i in this.selects) {
					$style(this.selects[i], 'visibility', 'hidden');
				}*/
				this.isSelectsVisible = false;
			}
		},
		
		// LOCATION
		
		genObjectFromQuery : function(str) {
			if (str) {
				var obj= {};
				var prop;
				var props = str.split('&');
				for (var i = 0; i < props.length; i++) {
					prop = props[i].split('=');
					if (i == 0) {
						if (prop[0].indexOf('?') != -1) {
							prop[0] = prop[0].substr(prop[0].indexOf('?')+1);
						}
					}
					obj[prop[0]] = prop[1];
				}
				return obj;
			}
			return null;
		},
		
		getQueryParamValue : function(param, str) {
			var q = str || document.location.search || document.location.hash || document.location.href.hash;
			if (q) {
				var startIndex = q.indexOf(param+'=');
				var endIndex = (q.indexOf('&', startIndex) > -1) ? q.indexOf('&', startIndex) : q.length;
				if (q.length > 1 && startIndex > -1) {
					return q.substring(q.indexOf('=', startIndex)+1, endIndex);
				}
			}
			return '';
		},
		
		getQueryObj : function(str) {
			var q = str || document.location.search || document.location.hash || document.location.href.hash;
			if (!q.indexOf('?')) q = q.substr(1);
			var obj = {};
			if (q) {
				var arr = q.split('&');
				var arr1;
				for (var i = 0,len = arr.length; i < len; i++) {
					arr1 = arr[i].split('=');
					if (arr1[0].indexOf('?') != -1) {
						arr1[0] = arr1[0].substr(arr1[0].indexOf('?')+1);
					}
					obj[arr1[0]] = arr1[1];
				}
			}
			return obj;
		},
		
		isLocal : function() {
			return document.location.href.indexOf('file:') == 0;
		},
		
		// CUSTOMIZING
		// even/odd styling
		stripe : function(layer, tags, evenClass, oddClass, everyN, oddIsFirst, leaveHeights) {
			if (!everyN) everyN = 1;
			var even = oddIsFirst;
			var mainObj;
			if (!(mainObj = $element(layer))) {
				return;
			}
			if (!evenClass) {
				evenClass = 'even';
			}
			if (!oddClass) {
				oddClass = 'odd';
			}
			var elements = this.getElementsIn(mainObj, tags, 0);
			var el;
			var tmp = [];
			var maxH = 0;
			for (var i = 0; i < elements.length; i++) {
				el = elements[i];
				if (!(i%everyN)) {
					even = !even;
					el.style.clear = 'left';
				} else {
					el.style.clear = '';
				}
				el.className = even ? evenClass : oddClass;
				if (!leaveHeights) {
					$style(el, 'height', this.isIE6() ? 0 : 'auto');
					//$style(el, 'height', 'auto');
					if (el.style.clear == 'left') {
						for (var n = 0; n < tmp.length; n++) {
							$style(tmp[n], 'height', maxH+'px');
						}
						tmp = [];
						maxH = 0;
					}
					maxH = Math.max(this.getElementHeight(el), maxH);
					//Debug.log(el.innerHTML+' '+this.getElementHeight(el)+' '+maxH);
					tmp.push(el);
				}
			}
		},
		
		getElementsIn : function(obj, tags, depth, elements) {
			if (!elements) {
				elements = [];
			}
			if (!depth) {
				depth = 0;
			}
			var els = obj.getElementsByTagName(tags[depth]);
			if (tags[depth+1]) {
				for (var i = 0; i < els.length; i++) {
					elements = arguments.callee(els[i], tags, depth+1, elements);
				}
			} else {
				for (var i = 0; i < els.length; i++) {
					elements.push(els[i]);
				}
			}
			return elements;
		},
		
		// OTHERS
		// remove the flickering
		fixBgImageCache : function() {
			try {
				document.execCommand('BackgroundImageCache', false, true);
			} catch(e) {}
		}
		
	});

	sjs.Utils.fixBgImageCache();

	if ($shortcut) {
		$shortcut(['e', 'element'], sjs.Utils, 'element');

		$shortcut('body', sjs.Utils, 'getBody');

		$shortcut('stripe', sjs.Utils, 'stripe');

		$shortcut('head', sjs.Utils, 'getHead');

		$shortcut('html', sjs.Utils, function(){
			if (arguments.length == 1) {
				return sjs.Utils.getHtml.apply(sjs.Utils, arguments);
			} else {
				sjs.Utils.setHtml.apply(sjs.Utils, arguments);
			}
		});
	}
	
})();